/**
 * 
 */
package co.edu.udem.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.zip.GZIPOutputStream;

import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import co.edu.udem.common.util.CoreMessageCodes;
import co.edu.udem.domain.User;
import co.edu.udem.service.GenericDTO;
import co.edu.udem.service.GenericService;
import co.edu.udem.service.ServiceResponse;
import co.edu.udem.service.login.LoginService;


/**
 * @since 18/07/2012
 */
@Controller
public class BaseController {

  protected static Logger logger = Logger.getLogger("controller");

  /** core properties. */
  @Autowired
  private Properties coreProperties;

  @Resource(name = "loginService")
  private LoginService loginService;

  /** Define the double TOKEN. */
  private final String TOKEN = System.getProperty("line.separator");

  /**
   * creates a json response.
   * 
   * @param responseCode responseCode.
   * @param responseDescriptionKey responseDescriptionKey.
   * @return ServiceResponse
   * @throws JSONException
   */
  public ServiceResponse createResponse(String responseCode, String responseDescriptionKey) {
    ServiceResponse serviceResponse = new ServiceResponse();
    serviceResponse.setResponseCode(responseCode);
    serviceResponse.setResponseDescription(coreProperties.getProperty(responseDescriptionKey));
    return serviceResponse;
  }

  public void consumeService(GenericService genericService, String userCode, String password, String actorType,
      String encryptedSessionId, String dateAuthentication, HttpServletResponse servletResponse, Object... params)
      throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException,
      NoSuchPaddingException, BadPaddingException, InvalidAlgorithmParameterException {
    OutputStream responseOutputStream = null;
    GZIPOutputStream gzipOutputStream = null;
    try {
      ServiceResponse serviceResponse;

      User user = loginService.validateSession(userCode, password, Integer.valueOf(actorType));
      if (user == null) {
        serviceResponse = createResponse(CoreMessageCodes.INVALID_USER_PASSWORD_CODE,
            CoreMessageCodes.INVALID_USER_PASSWORD);
      } else {
        serviceResponse = createResponse(CoreMessageCodes.SUCCESSFUL_AUTHENTICATION_CODE,
            CoreMessageCodes.SUCCESSFUL_AUTHENTICATION);
        serviceResponse.setPassword(password);
        serviceResponse.setSessionId("asdfa");
        servletResponse.setHeader("Content-Encoding", "gzip");
        servletResponse.setContentType("application/octet-stream");
        serviceResponse.setUserType(String.valueOf(user.getUserType()));
        serviceResponse.setUserTypeDescription(user.getUserTypeDescription());
        serviceResponse.setUserName(userCode);

        List<GenericDTO> objectList = genericService.getObjectList(new Date(), null, params);
        servletResponse.setHeader("cLength", String.valueOf(objectList.size()));
        responseOutputStream = servletResponse.getOutputStream();
        gzipOutputStream = new GZIPOutputStream(responseOutputStream);
        writeItemInformation(gzipOutputStream, objectList);
      }
    } finally {
      if (gzipOutputStream != null) {
        gzipOutputStream.close();
      }
    }
  }

  /**
   * Method that write information into OutputStream.
   * @param gzipOutputStream gzipOutputStream
   * @param objectList objectList
   * @throws IOException IOException
   */
  private void writeItemInformation(GZIPOutputStream gzipOutputStream, List<GenericDTO> objectList) throws IOException {
    StringBuilder responseAdd = new StringBuilder("");
    int count = 0;
    for (GenericDTO objectDTO : objectList) {
      objectDTO.writeValuesToStringBuilder(responseAdd);
      responseAdd.append(TOKEN);
      count++;
      if (count == 1000) {
        gzipOutputStream.write(responseAdd.toString().getBytes("UTF-8"));
        responseAdd = new StringBuilder("");
        count = 0;
      }
    }
    if (count < 1000) {
      gzipOutputStream.write(responseAdd.toString().getBytes("UTF-8"));
      responseAdd = null;
      count = 0;
    }
  }

}
